package com.dede.lib;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Encoder;

public class NetEaseWeb {

    // 加密
    private static String encrypt(String sSrc, String sKey) {
        if (sSrc == null || sKey == null) {
            return null;
        }
        SecretKeySpec skeySpec = new SecretKeySpec(sKey.getBytes(), "AES");
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式"
            IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes());//使用CBC模式，需要一个向量iv，可增加加密算法的强度
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(sSrc.getBytes());
            return new BASE64Encoder().encode(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        long s = System.currentTimeMillis();
        System.out.println(netEaseWebRequestUrl());
        // 生成的链接直接post请求，返回json内的url就是播放链接
        System.out.println((System.currentTimeMillis() - s));
    }

    public static String netEaseWebRequestUrl() {

        String jsonParams = "{\"csrf_token\": \"\", \"ids\": [27713963], \"br\": 320000}";

        String randomStr = randomStr(16);
        System.out.println("randomStr: " + randomStr);
        System.out.println("---------------------------");

        String nonce = "0CoJUm6Qyw8W8jud";
        String encrypt = encrypt(jsonParams, nonce);// 第一次加密
        encrypt = encrypt(encrypt, randomStr);// 第二次加密
        String params = null;
        try {
            params = URLEncoder.encode(encrypt, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println("params: " + params);

        String reverseRandomStr = new StringBuilder(randomStr).reverse().toString();// 反转字符串
        String hexStr = parseByte2HexStr(reverseRandomStr.getBytes());// 转16进制字符串

        String publicKey = "010001";
        String modulus = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7";

        String x = pow(hexStr, publicKey, modulus);
        String encSecKey = zfill(x, 256);
        System.out.println("encSecKey: " + encSecKey);

        System.out.println("=========================");

        String requestUrl = String.format("http://music.163.com/weapi/song/enhance/player/url?params=%1s&encSecKey=%2s", params, encSecKey);
        return requestUrl;
    }

    /**
     * 字符串右对齐，前面补0直到总长度为length，如果原本长度大于length就直接返回
     *
     * @param x      字符串
     * @param length 补0后的长度
     * @return
     */
    private static String zfill(String x, int length) {
        int l = x.length();
        if (l < length) {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < (256 - l); i++) {
                builder.append("0");
            }
            return builder.append(x).toString();
        } else {
            return x;
        }
    }

    /**
     * 快速幂算法 a^b%c
     *
     * @param aStr
     * @param bStr
     * @param zStr
     */
    private static String pow(String aStr, String bStr, String zStr) {
        int b = Integer.parseInt(bStr, 16);
        BigInteger a = new BigInteger(aStr, 16);
        BigInteger c = new BigInteger(zStr, 16);
        /*
         int PowerMod(int a, int b, int c)
         {
           int ans = 1;
           a = a % c;
           while (b > 0) {
               if(b % 2 == 1)
                   ans = (ans * a) % c;
               b = b / 2;
               a = (a * a) % c;
           }
           return ans;
         }
        */
        BigInteger ans = BigInteger.ONE;
        a = a.remainder(c);
        while (b > 0) {
            if (b % 2 == 1) {
                ans = ans.multiply(a).remainder(c);
            }
            b /= 2;
            a = a.pow(2).remainder(c);
        }
        return ans.toString(16);
    }

    /**
     * 将二进制转换成16进制字符串
     *
     * @param buf
     * @return
     */
    private static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i]);
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 生成指定长度的随机字符串[a-zA-Z0-9]
     *
     * @param length
     * @return
     */
    private static String randomStr(int length) {
        String all = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        int l = all.length();
        StringBuilder builder = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            builder.append(all.charAt(random.nextInt(l)));
        }
        return builder.toString();
    }
}